﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using SASystem.SAServiceRef;

namespace SASystem
{
    public partial class FamilyDownFrm : Form
    {
        FamilyInfo m_curFamilyInfo;
        List<ParameterInfo> m_keyParameters;
        List<ParameterInfo> m_nonCustomKeyParameters;
        List<ParameterInfo> m_customKeyParameters;

        List<TextBox> m_listTextBoxCustomParams;
        Dictionary<ListBox, ListBox> m_dictListBoxStart2End;
        Dictionary<ListBox, ListBox> m_dictListBoxEnd2Start;
        bool m_bListViewSelectionChanged;
        public FamilyDownFrm(FamilyInfo familyInfo)
        {
            InitializeComponent();

            m_curFamilyInfo = familyInfo;
            m_dictListBoxStart2End = new Dictionary<ListBox, ListBox>();
            m_dictListBoxEnd2Start = new Dictionary<ListBox, ListBox>();
            m_listTextBoxCustomParams = new List<TextBox>();
            m_bListViewSelectionChanged = true;
        }

        private void FamilyDownFrm_Load(object sender, EventArgs e)
        {
            InitDownloadDialogUI();
        }

        private void InitDownloadDialogUI()
        {
            this.Text = m_curFamilyInfo.DisplayName;
            m_keyParameters = SABLL.GetFamilyKeyParameters(m_curFamilyInfo.ID);

            if (m_keyParameters == null)
            {
                SABLL.ShowErrMsg(SABLL.GetLastErrMsg());
                return;
            }
            //
            m_nonCustomKeyParameters = new List<ParameterInfo>();
            m_customKeyParameters = new List<ParameterInfo>();

            foreach (ParameterInfo item in m_keyParameters)
            {
                if (item.IsCustom)
                {
                    m_customKeyParameters.Add(item);
                }
                else
                {
                    m_nonCustomKeyParameters.Add(item);
                }
            }

            InitListViewForNonCustomKeyParameters(m_nonCustomKeyParameters);
            InitTextBoxForCustomKeyParameters(m_customKeyParameters);

            //init model, drawing pictures.
            //get data.
            FamilyAttrInfo familyAttr = SABLL.GetFamilyAttrInfo(m_curFamilyInfo.ID);

            if (familyAttr == null)
            {
                SABLL.ShowErrMsg(SABLL.GetLastErrMsg());
                return;
            }

            string modelPicPath, drawPicPath;
            modelPicPath = System.IO.Path.Combine(SABLL.GetLocalCacheFolder(m_curFamilyInfo.ID.ToString()), familyAttr.ModelPicName);
            drawPicPath = System.IO.Path.Combine(SABLL.GetLocalCacheFolder(m_curFamilyInfo.ID.ToString()), familyAttr.DrawPicName);

            modelPicPath = SABLL.SaveBinaryByPath(modelPicPath, familyAttr.ModelPicBinary);
            drawPicPath = SABLL.SaveBinaryByPath(drawPicPath, familyAttr.DrawPicBinary);

            this.pictureBox_ModelPic.ImageLocation = modelPicPath;
            this.pictureBox_DrawingPic.ImageLocation = drawPicPath;
        }

        private void InitListViewForNonCustomKeyParameters(List<ParameterInfo> m_parameters)
        {
            int interval = 20;
            //add label.
            Size labelSize = this.label_NonCustomParamName1.Size;
            Point labelStartPoint = this.label_NonCustomParamName1.Location;


            //add listbox.
            Size listViewSize = this.listBox_NonCustomParamList1.Size;
            Point listViewStartLocation = this.listBox_NonCustomParamList1.Location;

            ListBox preListBox = null;
            ListBox firstListBox = null;
            ListBox newListView = null;
            int i = 0;
            foreach (ParameterInfo item in m_parameters)
            {
                Label newLabel = new Label();
                newLabel.Size = labelSize;
                newLabel.TextAlign = ContentAlignment.MiddleCenter;
                newLabel.Text = item.DisplayName;

                Point newLoc = labelStartPoint;
                newLoc.X = labelStartPoint.X + i * (interval + labelSize.Width);
                newLoc.Y = labelStartPoint.Y;
                newLabel.Location = newLoc;
                this.panel_NonCustom.Controls.Add(newLabel);

                newListView = new ListBox();
                newListView.Size = listViewSize;
                newListView.SelectionMode = SelectionMode.One;
                newListView.Tag = item;
                newListView.SelectedIndexChanged += new EventHandler(newListView_SelectedIndexChanged);
                Point new2Loc = listViewStartLocation;
                new2Loc.X = listViewStartLocation.X + i * (interval + listViewSize.Width);
                new2Loc.Y = listViewStartLocation.Y;
                newListView.Location = new2Loc;
                this.panel_NonCustom.Controls.Add(newListView);

                if (preListBox != null)
                {
                    m_dictListBoxStart2End.Add(preListBox, newListView);
                }

                m_dictListBoxEnd2Start.Add(newListView, preListBox);

                preListBox = newListView;

                if (i == 0) firstListBox = newListView;
                i++;
            }

            if (newListView != null)
            {
                //add last map.
                m_dictListBoxStart2End.Add(newListView, null);
            }

            //fill data for listviews.
            if (m_parameters.Count > 0)
            {
                List<ParameterValueInfo> emptyConstraint = new List<ParameterValueInfo>();
                List<ParameterValueInfo> retVals = SABLL.GetParamVals(m_nonCustomKeyParameters[0].ID, emptyConstraint);

                if (retVals == null)
                {
                    SABLL.ShowErrMsg(SABLL.GetLastErrMsg());
                    return;
                }

                for (int j = 0; j < retVals.Count; j++)
                {
                    firstListBox.Items.Add(retVals[j].Value);
                }

                firstListBox.SelectedIndex = 0;
            }
        }

        void newListView_SelectedIndexChanged(object sender, EventArgs e)
        {
            ListBox curListBox = (ListBox)sender;
            if (curListBox.Tag == null)
            {
                return;
            }
            OnListViewSelectionChanged(curListBox);

            m_bListViewSelectionChanged = true;
        }

        private void OnListViewSelectionChanged(ListBox listBox)
        {
            List<ParameterValueInfo> paramConstrains = this.GetParameterConstrains(listBox);

            ListBox nextListBox = this.GetNextListBox(listBox);
            if (nextListBox == null) return;

            ParameterInfo nextParamInfo = nextListBox.Tag as ParameterInfo;
            if (nextParamInfo == null) return;

            Guid parameterId = (nextListBox.Tag as ParameterInfo).ID;
            List<ParameterValueInfo> retVals = SABLL.GetParamVals(parameterId, paramConstrains);
            if (retVals == null)
            {
                SABLL.ShowErrMsg(SABLL.GetLastErrMsg());
                return;
            }
            nextListBox.Items.Clear();
            for (int i = 0; i < retVals.Count; i++)
            {
                nextListBox.Items.Add(retVals[i].Value);
            }

            if (nextListBox.Items.Count > 0)
            {
                //should invoke the newListView_SelectedIndexChanged event.
                nextListBox.SelectedIndex = 0;
            }
        }

        private List<ParameterValueInfo> GetParameterConstrains(ListBox listBox)
        {
            List<ParameterValueInfo> retList = new List<ParameterValueInfo>();

            if (listBox == null)
            {
                return retList;                
            }

            ParameterInfo curParamInfo = listBox.Tag as ParameterInfo;

            ParameterValueInfo newInfo = new ParameterValueInfo();
            newInfo.ID = curParamInfo.ID;
            newInfo.Value = Convert.ToString(listBox.SelectedItem);
            retList.Add(newInfo);

            ListBox tempListBox = GetPreListBox(listBox);

            while (tempListBox != null)
            {
                curParamInfo = tempListBox.Tag as ParameterInfo;
                newInfo = new ParameterValueInfo();
                newInfo.ID = curParamInfo.ID;
                newInfo.Value = Convert.ToString(tempListBox.SelectedItem);
                retList.Add(newInfo);
                tempListBox = GetPreListBox(tempListBox);
            }

            return retList;
        }

        private ListBox GetNextListBox(ListBox listBox)
        {
            ListBox retListBox = null;
            if (listBox != null)
            {
                if (m_dictListBoxStart2End.TryGetValue(listBox, out retListBox))
                    return retListBox;
            }

            return null;
        }

        private ListBox GetPreListBox(ListBox listBox)
        {
            if (listBox != null)
            {
                return m_dictListBoxEnd2Start[listBox];
            }

            return null;
        }

        private void InitTextBoxForCustomKeyParameters(List<ParameterInfo> m_parameters)
        {
            int interval = 10;
            //add label.

            Size labelSize = this.label_CustomParamName1.Size;
            Point labelStartPoint = this.label_CustomParamName1.Location;

            Size textBoxSize = this.textBox_CustomValue1.Size;
            Point textBoxStartLocation = this.textBox_CustomValue1.Location;

            int i = 0;
            foreach (ParameterInfo item in m_parameters)
            {
                int offsetY = i * (2 * interval + labelSize.Height + textBoxSize.Height);
                //add label.
                Label newLabel = new Label();
                newLabel.Size = labelSize;
                newLabel.TextAlign = ContentAlignment.MiddleLeft;
                //set parameter title.
                if (item.IsCustom)
                {
                    double lowLimit, upLimit;
                    bool success = SABLL.GetLimits(item.Tag, out lowLimit, out upLimit);
                    if (success)
                    {
                        newLabel.Text = String.Format("{0}[{1}-{2}]", item.DisplayName, lowLimit, upLimit);
                    }
                    else
                    {
                        newLabel.Text = item.DisplayName;
                    }
                }
                else
                {
                    newLabel.Text = item.DisplayName;
                }
                Point newLoc = labelStartPoint;
                newLoc.Y = labelStartPoint.Y + offsetY;
                newLoc.X = labelStartPoint.X;
                newLabel.Location = newLoc;
                this.panel_Custom.Controls.Add(newLabel);

                //add text box.
                TextBox newTextBox = new TextBox();
                newTextBox.Size = textBoxSize;
                newTextBox.Tag = item;
                Point new2Loc = textBoxStartLocation;
                new2Loc.Y = textBoxStartLocation.Y + offsetY;
                new2Loc.X = textBoxStartLocation.X;
                newTextBox.Location = new2Loc;
                if (item.IsCustom)
                {
                    //set text default value.
                    double dDefault;
                    if (SABLL.GetDefault(item.Tag, out dDefault))
                    {
                        newTextBox.Text = Convert.ToString(dDefault);
                    }

                    //add text change event.
                    double lowLimit, upLimit;
                    if (SABLL.GetLimits(item.Tag, out lowLimit, out upLimit))
                    {
                        newTextBox.TextChanged += new EventHandler(newTextBox_TextChanged);                       
                    }
                }
                this.panel_Custom.Controls.Add(newTextBox);
                m_listTextBoxCustomParams.Add(newTextBox);
                i++;
            }
        }

        void newTextBox_TextChanged(object sender, EventArgs e)
        {
             TextBox tb = (TextBox)sender;
            try
            {
                double curVal = Convert.ToDouble(tb.Text);

                ParameterInfo curParamInfo = tb.Tag as ParameterInfo;
                double lowLimit, upLimit;
                if (SABLL.GetLimits(curParamInfo.Tag, out lowLimit, out upLimit))
                {
                    if (curVal < lowLimit || curVal > upLimit)
                    {
                        tb.ForeColor = Color.Red;
                        return;
                    }
                }
            }
            catch (Exception)
            {
                tb.ForeColor = Color.Red;
                return;
            }

            tb.ForeColor = Color.Black;
            return;
        }

        private void button_cancel_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void tabControl_parameterSelection_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (((TabControl)sender).SelectedIndex == 1 && m_bListViewSelectionChanged)
            {
                DataTable dt = this.GetDataTableByUserDriverParameterSelection();
                InitSubFamilyTableGridView(dt);
                if (this.dataGridView_subFamilyTable.Rows.Count > 0)
	            {
		            this.dataGridView_subFamilyTable.Rows[0].Selected = true;
	            }
            }

            if (m_dictListBoxStart2End.Count > 0)
            {
                m_bListViewSelectionChanged = false;
            }
        }

        private void button_downLoad_Click(object sender, EventArgs e)
        {
            this.button_downLoad.Enabled = false;
            this.Cursor = Cursors.WaitCursor;
            Application.DoEvents();
            try
            {
                if (this.tabControl_parameterSelection.SelectedIndex == 0)
                {
                    DataTable dt = this.GetDataTableByUserDriverParameterSelection();
                    if (dt == null) return;
                    if (dt.Rows.Count > 1)
                    {
                        SABLL.ShowInfoMsg("结果有多项，请在[参数明细]中继续选择，默认选择第一组数据！");
                        this.tabControl_parameterSelection.SelectedIndex = 1;
                        this.Cursor = Cursors.Default;
                        this.button_downLoad.Enabled = true;
                        return;
                    }
                    else if(dt.Rows.Count == 1)
                    {
                        this.tabControl_parameterSelection.SelectedIndex = 1;
                    }
                }
                StartDownLoad();
            }
            catch (Exception ex)
            {
                SABLL.ShowErrMsg(ex.Message);
            }
            this.Cursor = Cursors.Default;
            this.button_downLoad.Enabled = true;
            return;
        }

        private void StartDownLoad()
        {
            DataGridViewRow curRow = SABLL.GetSelectedRow(this.dataGridView_subFamilyTable);

            //original part.
            Guid instanceId = Guid.Empty;
            if (curRow != null)
	        {
                //instant part.
                instanceId = new Guid(Convert.ToString(curRow.Cells[0].Value));
	        }
            
            Guid familyId = m_curFamilyInfo.ID;
            List<ParameterValueInfo> driveParameterVals = SABLL.GetDriveParameterVals(familyId, instanceId);
            if (driveParameterVals == null)
            {
                SABLL.ShowErrMsg(SABLL.GetLastErrMsg());
                return;
            }

            List<ParameterValueInfo> customParameterVals = this.GetAllCustomParameterVals();
            if (customParameterVals == null) return;

            bool success = ApplyCustomDriveParameters(ref driveParameterVals, customParameterVals);
            if (!success) return;

            List<ParameterInfo> driveParameterInfos = new List<ParameterInfo>();

            for (int i = 0; i < driveParameterVals.Count; i++)
			{
                ParameterInfo newParamInfo = SABLL.GetFamilyParameterInfo(driveParameterVals[i].ID);
               newParamInfo.Value = driveParameterVals[i].Value;
               driveParameterInfos.Add(newParamInfo);
			}

            //
            //show download frm, get the target path and file type.
            FamilyAttrInfo tempAttr = SABLL.GetFamilyAttrInfo(m_curFamilyInfo.ID);
           
            //find file name column id.
            int fileNameColId = -1;
            string fileName = m_curFamilyInfo.Name;
            for (int i = 0; i < this.dataGridView_subFamilyTable.Columns.Count; i++ )
            {
                ParameterInfo paramInfo = this.dataGridView_subFamilyTable.Columns[i].Tag as ParameterInfo;
                if (paramInfo == null)
                {
                    continue;
                }
                if (paramInfo.Name == "u_FileName")
                {
                    fileNameColId = i;
                    break;
                }
            }

            if (fileNameColId > -1)
            {
                fileName = Convert.ToString(curRow.Cells[fileNameColId].Value);
            }

            DownLoadFrm dlf = new DownLoadFrm(fileName);
            string targetPath = String.Empty;
            if (dlf.ShowDialog() == DialogResult.OK)
            {
                this.Cursor = Cursors.WaitCursor;
                targetPath = dlf.GetFilePath();
                success = SABLL.GeneratePart(m_curFamilyInfo.ID,instanceId, driveParameterInfos, targetPath);
                this.Cursor = Cursors.Default;

            }

            if (!success)
            {
                SABLL.ShowErrMsg(SABLL.GetLastErrMsg());
                return;
            }
            else if (success && System.IO.File.Exists(targetPath))
            {
                SABLL.ShowInfoMsg("下载成功："+ targetPath);
                return;
                // DownloadFinishedFrm dff = new DownloadFinishedFrm(targetPath);
               // dff.ShowDialog();
            }

        }

        private bool ApplyCustomDriveParameters(ref List<ParameterValueInfo> driveParameterVals, List<ParameterValueInfo> customParameterVals)
        {
            foreach (ParameterValueInfo customParamVal in customParameterVals)
            {
                foreach (ParameterValueInfo driveParamVal in driveParameterVals)
                {
                    if (driveParamVal.ID == customParamVal.ID)
                    {
                        driveParamVal.Value = customParamVal.Value;
                        break;
                    }
                }
            }
            return true;
        }

        private List<ParameterValueInfo> GetAllCustomParameterVals()
        {
            List<ParameterValueInfo> retList = new List<ParameterValueInfo>();

            foreach (TextBox item in m_listTextBoxCustomParams)
            {
                ParameterInfo curInfo = item.Tag as ParameterInfo;
                if (curInfo == null)
	            {
                    SABLL.ShowErrMsg("自定义参数数据丢失，请重新打开下载窗口！");
	                return null;
	            }
                if (item.ForeColor == Color.Red) //incorrect data. return.
                {
                    SABLL.ShowErrMsg(String.Format("自定义参数 [{0}] 的值 [{1}] 无效，请重新设置！", curInfo.DisplayName, item.Text));
                    return null;
                }

                ParameterValueInfo retInfo = new ParameterValueInfo();
                retInfo.ID = curInfo.ID;
                retInfo.Value = item.Text.Trim();
                retList.Add(retInfo);
            }

            return retList;
        }

        private void InitSubFamilyTableGridView(DataTable dt)
        {
            //
            this.dataGridView_subFamilyTable.ReadOnly = false;
            this.dataGridView_subFamilyTable.AllowUserToAddRows = true;
            this.dataGridView_subFamilyTable.AllowUserToDeleteRows = true;

            this.dataGridView_subFamilyTable.DataSource = dt;
            int cnt = this.dataGridView_subFamilyTable.Columns.Count;
            for (int i = 0; i < cnt; i++)
            {
                DataGridViewColumn curCol =  this.dataGridView_subFamilyTable.Columns[i];
                string parameterGuid = curCol.HeaderText;
                try
                {
                    curCol.Tag = parameterGuid;
                    ParameterInfo paramInfo = SABLL.GetFamilyParameterInfo(new Guid(parameterGuid));
                    if (paramInfo != null)
                    {
                        curCol.HeaderText = paramInfo.DisplayName;
                        curCol.Tag = paramInfo;
                    }
                }
                catch (Exception)
                {
                  
                }
            }
            if (cnt > 0)
            {
                this.dataGridView_subFamilyTable.Columns[0].Visible = false;
                this.dataGridView_subFamilyTable.Columns[1].Visible = false;
            }
            this.dataGridView_subFamilyTable.AllowUserToAddRows = false;
            this.dataGridView_subFamilyTable.AllowUserToDeleteRows = false;
            this.dataGridView_subFamilyTable.ReadOnly = true;
        }

        private DataTable GetDataTableByUserDriverParameterSelection()
        {
            ListBox lastListBox = null;
            //get the last list control.
            foreach (ListBox item in m_dictListBoxStart2End.Keys)
            {
                if (m_dictListBoxStart2End[item] == null)
                {
                    lastListBox = item;
                    break;
                }
            }

            List<ParameterValueInfo> paramConstraints = this.GetParameterConstrains(lastListBox);

            DataTable dt = SABLL.GetSubFamilyTable(m_curFamilyInfo.ID, paramConstraints);

            if (dt == null)
            {
                SABLL.ShowInfoMsg(SABLL.GetLastErrMsg());
            }
            return dt;
        }

        private void pictureBox_DrawingPic_MouseHover(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Hand;
        }

        private void pictureBox_DrawingPic_Click(object sender, EventArgs e)
        {
            PicDetailFrm pdf = new PicDetailFrm(this.pictureBox_DrawingPic.ImageLocation);
            pdf.Show();
        }

        private void pictureBox_DrawingPic_MouseLeave(object sender, EventArgs e)
        {
            this.Cursor = Cursors.Default;
        }

        private void button_downDoc_Click(object sender, EventArgs e)
        {
            FamilyAttrInfo familyAttrInfo = SABLL.GetFamilyAttrInfoByType(m_curFamilyInfo.ID, 
                FamilyAttrType.kReference);

            if (familyAttrInfo != null && !String.IsNullOrEmpty(familyAttrInfo.ReferenceName) && 
                familyAttrInfo.ReferenceBinary !=null && familyAttrInfo.ReferenceBinary.Length > 0)
            {
                string path = SABLL.SaveFileBrowser(FileType.kDocument, familyAttrInfo.ReferenceName);

                if (!String.IsNullOrEmpty(path))
                {
                    string referencePath = SABLL.SaveBinaryByPath(path, familyAttrInfo.ReferenceBinary);

                    SABLL.ShowInfoMsg(String.Format("保存文档成功！保存位置：{0}", path));
                }
            }
            else
            {
                //no referece document.
                SABLL.ShowInfoMsg(@"无可下载的文档资料！");
            }
        }
    }
}
